package com.song.server;

import com.song.transport.RPCRequest;
import com.song.transport.RPCResponse;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.util.ReferenceCountUtil;
import lombok.extern.slf4j.Slf4j;

@Slf4j(topic = "c.NettyServerHandler")
public class NettyServerHandler extends SimpleChannelInboundHandler<RPCRequest> {
    private static MyRequestHandler requestHandler;

    static {
        requestHandler = new MyRequestHandler();
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, RPCRequest msg) throws Exception {
        try {
//服务器接收到请求: RPCRequest(interfaceName=com.song.api.HelloService, methodName=hello, parameters=[HelloObject(id=13, message=Hello, I am s1)], paramTypes=[class com.song.api.HelloObject], paramterValue=null)
            log.info("服务器接收到请求: {}", msg);
            String interfaceName = msg.getInterfaceName();//针对msg与客户端通用的接口  HelloService

            //Object service = serviceRegistry.lookupService(interfaceName);//获取服务端的相对应服务信息   返回类型 InetSocketAddress  此处错误 应该为通用接口的类名

            //Object service = Class.forName(interfaceName);//有问题  客户端和服务端的全限定名称不一样  通过接收到的Request 获取到通用接口的名称 反射 获取该服务端的通用接口类

            Object result = requestHandler.handle(msg);//动态反射  将msg 传入 对应的接口的实现方法，返回结果作为RPCResponse的返回信息

            if (ctx.channel().isActive() && ctx.channel().isWritable()) {

                ChannelFuture future = ctx.writeAndFlush(RPCResponse.success(result, msg.getRequestId()));//AIO异步操作 将结果转成RPCResponse类结构 writeAndFlush()方法将数据  写入并立马发出
                future.addListener(ChannelFutureListener.CLOSE);//添加监听器 消息发送完毕后在去关闭连接 异步等待channel关闭
            } else {
                log.info("通道不可写");
            }
        } finally {
            ReferenceCountUtil.release(msg);
        }
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        log.error("处理过程调用时有错误发生:");
        cause.printStackTrace();
        ctx.close();
    }
}
